<?php

defined ( 'WX_ROOT' ) or die ( 'Not Defined WX_ROOT' );
/**
 */
class WxBase {
	
	protected $params   = NULL;
	protected $errors   = NULL;
	protected $response = NULL;
	protected $apiUrl   = NULL;
	protected $configGroup = 'yx';
	/**
	 * 微信返回的原始数据
	 * @var string
	 */
	protected $originalRespose = NULL;
	
	public  function setParams($key,$val=NULL){
		$this->params[$key] = $val;
		return $this;
	}
	/**
	 * 生成参数数组
	 */
	protected function generateParams(){
		
		foreach( array('appid','mch_id') as $key ){
			if ( empty($this->params[$key]) ) {
				$this->params[$key]= $this->config($key);
			}
		}
// 		$this->params['appid']  = $this->config('appid');
// 		$this->params['mch_id'] = $this->config('mch_id');
		$this->params['nonce_str'] = uniqid();
		$this->params['sign'] = self::sign($this->params,$this->config('key'));
	}
	protected function setError($msg='',$code='FAIL'){
		$this->errors['msg'] = $msg;
		$this->errors['code'] = $code;
	}
	public function getErrors(){
		return $this->errors;
	}
	public function getOriginalRespose(){
		return $this->originalRespose;
	}
	
	
	/**
	 * 解析返回的XML数据并验证结果是否为SUCCESS
	 * @param array $response
	 * @return boolean
	 */
	protected function parseResponse($response,$type='xml'){
		if ( 'xml' == $type ) {
			$response = self::XML2Array($response);
		}
		
		
		$this->response = $response;
		
		$success = isset($response['return_code']) 
				&& isset($response['result_code']) 
				&& $response['return_code'] = 'SUCCESS' 
				&& $response['result_code']=='SUCCESS';
		if ( $success ) {
			return TRUE;
		}else{
			foreach ($response as $k=>$v){
				switch ($k) {
					case 'return_code':
					case 'return_msg':
					case 'result_code':
					case 'err_code':
					case 'err_code_des':
						$this->errors[$k] = $v;
						break;
				}
			}
			return FALSE;
		}
		
		
	}
	
	/**
	 * 解析返回的XML数据并验证结果是否为SUCCESS
	 * @param array $response
	 * @return boolean
	 */
	protected function parseResponseNew($response,$type='xml'){
		if ( 'xml' == $type ) {
			$response = self::XML2Array($response);
		}
	
	
		$this->response = $response;
		
		$success = isset($response['return_code'])
		&& isset($response['result_code'])
		&& $response['return_code'] = 'SUCCESS'
				&& $response['result_code']=='SUCCESS';
		if ( $success ) {
			return $response;
		}else{
			foreach ($response as $k=>$v){
				switch ($k) {
					case 'return_code':
					case 'return_msg':
					case 'result_code':
					case 'err_code':
					case 'err_code_des':
						$this->errors[$k] = $v;
						break;
				}
			}
			return $response;
// 			return FALSE;
		}
	
	
	}
	
	protected  function request($needParseXML=TRUE){
		$this->generateParams();
		$sendXML = self::toXmlString($this->params);
		debug('sendParams',$this->params);
		$response  = self::curlSendXml($this->apiUrl, $sendXML);
		if ( $needParseXML ) {
			if ( $this->parseResponse($response) ){
				return $this->response;
			}else{
				return FALSE;
			}
		}
	
		return $response;
	}
	
	public function setConfigGroup($group){
		$this->configGroup = $group;
	}
	
	
	/**
	 * 获取配置参数
	 * 
	 * @param string  参数字段名
	 *        	<p>--appid	 : AppID
	 *        	<p>--mch_id	 : 商户号
	 *        	<p>--appSecret : AppSecret
	 *        	<p>--key		 : 商户key
	 * @return string
	 */
	protected function config($item = '',$group='') {
		static $cfg = NULL;
		if (NULL === $cfg) {
			$file = WX_ROOT . 'config.php';
			if (! file_exists ( $file )) {
				trigger_error ( '找不到配置文件', E_USER_ERROR );
			}
			$cfg = include ($file);
		}
		$group = empty($group) ? $this->configGroup : $group;
		if( empty($cfg[$group][$item]) ){
			return NULL;
		}
		return $cfg[$group][$item];
		
// 		if (empty ( $item )) {
// 			return $cfg;
// 		}
// 		return isset ( $cfg [$item] ) ? $cfg [$item] : NULL;
	}
	
	/**
	 * 计算签名
	 * 
	 * @param array|object $params        	
	 * @return string
	 */
	protected  function sign($params,$key='') {
		$params = ( array ) $params;
		$params = array_filter ( $params );
		ksort ( $params );
		$str = '';
		foreach ( $params as $k => $v ) {
			$str .= $k . '=' . $v . '&';
		}
		$str .= 'key=' . $key;
		$sign = md5 ( $str );
		return strtoupper ( $sign );
	}
	/**
	 * 将参数转为XML字符串
	 * 
	 * @param array|object $params        	
	 * @return string
	 */
	static function toXmlString($params) {
		$xml = '<xml>';
		foreach ( $params as $k => $v ) {
			$xml .= "<$k><![CDATA[$v]]></$k>";
		}
		$xml .= '</xml>';
		return $xml;
	}
	/**
	 * curl发送xml数据
	 * 
	 * @param string $url        	
	 * @param string $xml        	
	 * @param string $sslPemFile        	
	 * @param string $sslPemKeyFile        	
	 * @return boolean array
	 */
	static function curlSendXml($url, $xml, $sslPemFile = NULL, $sslPemKeyFile = NULL) {
		$ch = curl_init ();
		curl_setopt ( $ch, CURLOPT_URL, $url );
		curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );
		curl_setopt ( $ch, CURLOPT_HEADER, 0 );
		// 超时时间
		curl_setopt ( $ch, CURLOPT_TIMEOUT, 30 );
		curl_setopt ( $ch, CURLOPT_SSL_VERIFYPEER, FALSE );
		curl_setopt ( $ch, CURLOPT_SSL_VERIFYHOST, FALSE );
		if (! empty ( $sslPemFile ) && file_exists ( $sslPemFile )) {
			// 设置证书
			curl_setopt ( $ch, CURLOPT_SSLCERTTYPE, 'PEM' );
			curl_setopt ( $ch, CURLOPT_SSLCERT, $sslPemFile );
		}
		if (! empty ( $sslPemKeyFile ) && file_exists ( $sslPemKeyFile )) {
			// 设置密匙
			curl_setopt ( $ch, CURLOPT_SSLKEYTYPE, 'PEM' );
			curl_setopt ( $ch, CURLOPT_SSLKEY, $sslPemKeyFile );
		}
		
		// 设置post数据
		curl_setopt ( $ch, CURLOPT_POST, 1 );
		curl_setopt ( $ch, CURLOPT_POSTFIELDS, $xml );
		
		
		
		$rtn = curl_exec ( $ch );
		
		debug('curlSend',$xml);
		debug('curlReturn',$rtn);
		if ($rtn === false) {
			$msg ['error'] = curl_error ( $ch );
			$msg ['errno'] = curl_errno ( $ch );
			$msg ['xml'] = $xml;
			curl_close ( $ch );
			// TODO错误处理
			var_dump ( $msg );
			die ();
			return FALSE;
		}
		curl_close ( $ch );
		
		return $rtn;
	}
	/**
	 * 将xml字符串转为数组
	 * 
	 * @param string $xml        	
	 * @return array boolean
	 */
	static function XML2Array($xml) {
		libxml_use_internal_errors ( true );
		$xml = simplexml_load_string ( $xml ); // 解析失败返回false
		if ($xml) {
			$rtn = array ();
			foreach ( $xml as $k => $v ) {
				$rtn [$k] = ( string ) $v;
			}
			return $rtn;
		} else {
			$errs = libxml_get_errors (); // 捕获错误
			libxml_clear_errors ();
			return FALSE;
		}
	}
	
	static function getServerIP(){
		static $ip = NULL;
		if( NULL === $ip ){
			if( defined('SERVER_IP') && SERVER_IP  ){
				$ip = SERVER_IP;
			}else if( isset($_SERVER['SERVER_ADDR']) ){
				$ip = $_SERVER['SERVER_ADDR'];
			}else{
				$ip = '120.27.129.204';//服务器IP
			}
		}
		return $ip;
	}
}
